

package VisAVisTab;

import com.hp.hpl.jena.ontology.*;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.rdql.*;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.sql.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;


public class OntQueryPanel extends JPanel implements ActionListener,DropTargetListener{
    
    ConnectInfoPanel connectInfoPanel;
    String  ontQuery;
    OntologyPanel ontPanel;
    PostgresPanel pgPanel;
    MySQLPanel mySQLPanel;
    JButton btnExec;
    JTextField queryField;
    
    /** Creates a new instance of OntQueryPanel */
    public OntQueryPanel(ConnectInfoPanel CIPanel) {
        
        connectInfoPanel=CIPanel;
        ontPanel=CIPanel.ontPanel;
        
        
        setLayout(new FlowLayout(FlowLayout.CENTER));
        
        JLabel label = new JLabel("Insert RDQL Query:");
        add(label);
        
        queryField=new JTextField(60);
        DropTarget dropTarget=new DropTarget(queryField,this);
        add(queryField);
        
        btnExec=new JButton("Execute");
        btnExec.addActionListener(this);
        add(btnExec);
        
        
        
    }
    
    //Handle action events
    public void actionPerformed(ActionEvent event) {
        Object source = event.getSource();
        pgPanel=connectInfoPanel.pgPanel;
        mySQLPanel=connectInfoPanel.mySQLPanel;
        
        //if button "Execute" is pressed
        if ((source==btnExec)&&(ontPanel.ontModel!=null)){
            
            String basePrefix=ontPanel.ontModel.getNsPrefixURI("");
            DatatypeProperty dp=ontPanel.ontModel.getDatatypeProperty(basePrefix+"queryString");
            if (dp!=null){
                ontQuery=queryField.getText();
                String base=dp.getLabel(null);
                boolean sthWrong=false;
                //ontQuery="SELECT ?x,?y WHERE ( ?y, <http://www.owl-ontologies.com/unnamed.owl#queryString>  , ?x)";
                //ontQuery="SELECT ?x, ?y, ?z WHERE (?x, ?y, ?z)";
                Vector tables=new Vector();
                Vector resourcesFound=new Vector();
                try{
                    Query query = new Query(ontQuery);
                    
                    // Need to set the source if the query does not.
                    query.setSource(ontPanel.ontModel);
                    QueryExecution qe = new QueryEngine(query) ;
                    QueryResults results = qe.exec() ;
                    Iterator iter = results;
                    Vector v=new Vector();
                    Vector vres=new Vector();
                    while (iter.hasNext()) {
                        ResultBinding res = (ResultBinding)iter.next() ;
                        Iterator nam=res.names();
                        //find the number of variables in the query and store it to v
                        while(nam.hasNext()){
                            v.addElement(nam.next().toString()) ;
                        }
                        
                        //store the results of the RDQL query in a vector
                        for (int i=0;i<v.size();i++){
                            Vector temp=new Vector();
                            temp.addElement(((RDFNode)res.get(v.elementAt(i).toString())).toString());
                            vres.add(temp);
                        }
                        
                        
                        
                    }
                    results.close() ;
                    Iterator i=dp.listDomain();
                    
                    //add to a vector all the results of the RDQL query that are classes and are already mapped
                    while (i.hasNext()){
                        Resource current =(Resource)i.next();
                        for (int j=0;j<vres.size();j++){
                            Vector cur=(Vector)vres.elementAt(j);
                            if ((cur.contains(current.getURI()))&&(!resourcesFound.contains(current.getURI())))
                                resourcesFound.addElement(current.getURI());
                        }
                    }
                    
                    //check whether the mappings refer to the database connected
                    boolean agreement=false;
                    if (base.contains("PostgreSQL")&&(pgPanel!=null)){
                        if (base.equals("PostgreSQL-"+pgPanel.databaseSelected)) agreement=true;
                        else  JOptionPane.showMessageDialog(null,"Make sure you are connected to the correct PostgreSQL database",
                                "Wrong Connection",
                                JOptionPane.ERROR_MESSAGE);
                    } else if (base.contains("MySQL")&&(mySQLPanel!=null)){
                        if (base.equals("MySQL-"+mySQLPanel.databaseSelected)) agreement=true;
                        else  JOptionPane.showMessageDialog(null,"Make sure you are connected to the correct MySQL database",
                                "Wrong Connection",
                                JOptionPane.ERROR_MESSAGE);
                    }
                    if (agreement){
                        //for each RDQL query result retrieve the database query,execute it and show the results in a new frame
                        for (int j=0;j<resourcesFound.size();j++){
                            //retrieve the database query which is an underlying result of the RDQL query
                            DefaultTableModel dm = new DefaultTableModel();
                            JTable resultsTable=new JTable(dm);
                            OntResource resource=ontPanel.ontModel.getOntResource(resourcesFound.elementAt(j).toString());
                            String dbQuery=resource.getPropertyValue(dp).toString();
                            try{
                                //execute the database query
                                ResultSet ret = null;
                                if ((base.contains("PostgreSQL-"))&&(pgPanel!=null)){
                                    if (base.equals("PostgreSQL-"+pgPanel.databaseSelected)){
                                        Connection cur_connection=pgPanel.con;
                                        java.sql.Statement myStmt;
                                        myStmt = cur_connection.createStatement();
                                        ret = myStmt.executeQuery(dbQuery);
                                    }
                                } else if ((base.contains("MySQL-"))&&(mySQLPanel!=null)){
                                    if (base.equals("MySQL-"+mySQLPanel.databaseSelected)){
                                        Connection cur_connection=mySQLPanel.con;
                                        PreparedStatement myStmt;
                                        String label=dp.getLabel(null);
                                        myStmt = cur_connection.prepareStatement("USE "+label.substring(label.indexOf('-')+1));
                                        myStmt.execute("USE "+label.substring(label.indexOf('-')+1));
                                        myStmt = cur_connection.prepareStatement(dbQuery);
                                        ret = myStmt.executeQuery(dbQuery);
                                    }
                                }
                                ResultSetMetaData rmeta=ret.getMetaData();
                                int numColumns=rmeta.getColumnCount();
                                
                                //fill the table
                                Vector colNames=new Vector();
                                for(int k=1;k<=numColumns;k++) {
                                    colNames.addElement(rmeta.getColumnName(k));
                                }
                                
                                Vector rows=new Vector();
                                while(ret.next()){
                                    Vector newRow=new Vector();
                                    for(int k=1;k<=numColumns;k++)
                                        newRow.addElement(ret.getString(k));
                                    rows.addElement(newRow);
                                }
                                ret.close();
                                dm.setDataVector(null,colNames);
                                for (int k=0;k<rows.size();k++){
                                    Vector currentRow=(Vector)rows.elementAt(k);
                                    dm.addRow(currentRow);
                                    
                                }
                                resultsTable.setModel(dm);
                                tables.addElement(resultsTable);
                                
                            }catch(Exception ex){
                                JOptionPane.showMessageDialog(null,"Make sure you are connected to the database the mappings refer to",
                                        "No Connection found",
                                        JOptionPane.ERROR_MESSAGE);
                                sthWrong=true;
                            }
                        }
                    } else {
                        JOptionPane.showMessageDialog(null,"Make sure you are connected to the database the mappings refer to",
                                "No Connection found",
                                JOptionPane.ERROR_MESSAGE);
                        sthWrong=true;
                    }
                }catch(Exception ex){
                    JOptionPane.showMessageDialog(null,"The syntax of the RDQL query appears to be wrong.Please try again.",
                            "Wrong RDQL Query",
                            JOptionPane.ERROR_MESSAGE);
                    sthWrong=true;
                }
                
                if ((resourcesFound.size()!=0)&&!sthWrong){
                    //create a new frame where the results will be displayed
                    JFrame resultsFrame=new JFrame("results");
                    GridBagLayout gridbag=new GridBagLayout();
                    GridBagConstraints gbc=new GridBagConstraints();
                    resultsFrame.setLayout(gridbag);
                    
                    for (int i=0;i<resourcesFound.size();i++){
                        JTable table=(JTable)tables.elementAt(i);
                        //resourcesFound has the same number of elements as tables does
                        String fullName=resourcesFound.elementAt(i).toString();
                        String localName=fullName.substring(fullName.indexOf('#')+1);
                        
                        
                        JLabel label=new JLabel("Class "+localName);
                        JScrollPane sp=new JScrollPane(table);
                        ontPanel.buildConstraints(gbc,i,0,1,1,100,4,GridBagConstraints.NONE);
                        gridbag.setConstraints(label,gbc);
                        resultsFrame.add(label);
                        ontPanel.buildConstraints(gbc,i,1,1,1,100,96,GridBagConstraints.BOTH);
                        gridbag.setConstraints(sp,gbc);
                        resultsFrame.add(sp);
                    }
                    resultsFrame.pack();
                    resultsFrame.setVisible(true);
                } else if ((resourcesFound.size()==0)&&!sthWrong){
                    JOptionPane.showMessageDialog(null,"There are no results for the query you submitted.",
                            "No Results Found",
                            JOptionPane.INFORMATION_MESSAGE);
                }
            }
            else {
                JOptionPane.showMessageDialog(null,"There are no mappings available",
                            "No Mappings Done",
                            JOptionPane.INFORMATION_MESSAGE);
            }
        }
        else{
           JOptionPane.showMessageDialog(null,"You have to open an ontology before executing a query.",
                            "No Ontology Opened",
                            JOptionPane.ERROR_MESSAGE); 
        }
    }
    
    //reject drop actions in the RDQL query textfield
    public void drop(DropTargetDropEvent event) {
        if (event.getDropTargetContext().getComponent()==queryField)
            event.rejectDrop();
        
    }
    
    public void dragExit(DropTargetEvent event) {
        //System.out.println( "dragExit");
    }
    
    public void dropActionChanged( DropTargetDragEvent event ) {
    }
    
    
    public void dragOver(DropTargetDragEvent event) {
        // System.out.println( "dragOver");
    }
    
    public void dragEnter(DropTargetDragEvent event) {
        
    }
    
    
    
}
